#商品推荐算法(余弦相似度)
'''
点击 = 1         2+3.6+0+2.97+0+1.3  =  5.6 +3.27   =8.87
收藏 = 5         0+1.08+0+0+0+1.3 = 2.38
付款 = 10
搜索 = 3
                                评分矩阵
用户  物品  操作              1   2   3   4   5
A   1   点击              A   1   5   0   10  3
A   2   收藏              B   3   0   3   0   5
A   4   付款              C   0   10  0   5   0
A   5   搜索         =》
B   3   付款
B   1   搜索
B   5   收藏
C   2   付款
C   4   收藏
'''
import numpy as np;
#得出评分矩阵
def loadData(file):
    print("——开始得出评分矩阵——")
    data = {}
    for i,cols in enumerate(file):
        user,item,score = cols.split(",")
        data.setdefault(user,{});
        try:
            data[user][item] = int(data[user][item]) + int(score) #相同的物品,分值相加
        except KeyError:
            data[user][item] = int(score);
    print(data)
    return data;
#得出相似度矩阵(余弦相似度 COS<a,b> = Xa*Xb / (√Xa^2 + Ya^2  * √Xb^2 + Yb^2 ) )
def getProximityMatrix(scoreMap):
    print("——开始计算相似度矩阵——")
    result = {}
    maxN = 0
    #得到最大行数
    for i,item in enumerate(scoreMap.values()):
        num = int(max(item.keys()))
        if num > maxN:
            maxN=num
    for item in range(1,maxN+1):
        for j in range(1,maxN+1):
            num=0.00
            div1 = 0.00
            div2 = 0.00
            for i,user in enumerate(scoreMap.keys()):
                try:
                    n1 = scoreMap[user][str(item)]
                except KeyError:  #没有则 为0
                    n1 = 0.00
                try:
                    n2 = scoreMap[user][str(j)]
                except KeyError:  #没有则 为0
                    n2 = 0.00
                num += n1 * n2
                div1 += n1**2  #平方
                div2 += n2**2  #平方
            div = div1**0.5 * div2**0.5  #根号相乘
            try:
                num = round(num/div,2)  #保留两位小数
            except ZeroDivisionError:
                num=0
            #设置相似度矩阵
            result.setdefault(item,{})
            result[item][j] = num
    print(result)
    return result
#根据相似度矩阵 与 评分矩阵得出推荐列表
def getRecommend(scoreMap,matrix):
    print("——开始得出推荐列表——")
    result = {}
    for user in scoreMap.keys():
        for i in range(1,len(matrix)+1):
            num =0;
            for j in range(1,len(matrix[i])+1):
                try:
                    num += scoreMap[user][str(j)] * matrix[i][j]
                except KeyError:
                    continue
            result.setdefault(user,{})
            result[user][i]=round(num,1)
    print(result)
    return result
#将用户已经有的操作 推荐列表分值 置0  #返回推荐列表分值最高的。
def setZeroMatrix(scoreMap,matrix):
    print("——得出推荐物品结果——")
    result = {}
    for user in scoreMap.keys():
        for item in scoreMap[user].keys():
            matrix[user][int(item)] = 0 #置零
        num =  max(matrix[user].values())  #找最高分值
        for key in matrix[user].keys():   #找最高分值的 物品
            if num==matrix[user][key]:
                result[user] =key
    print(matrix)
    return result
if __name__ == '__main__':
    f=open("file1.txt",encoding='UTF-8')
    txt = f.read();
    w = txt.split("\n")
    scoreMap = loadData(w)
    result = getProximityMatrix(scoreMap)
    result= getRecommend(scoreMap,result)
    result= setZeroMatrix(scoreMap,result)
    print(result)
